    # -*- coding: utf-8 -*-
from __future__ import unicode_literals
import random
try:
    from tkinter import *
except ImportError:
    from Tkinter import *

#定义墙的画法
class Block():
    def __init__(self, mmap, x, y, direction=None):
        self.walls = [True, True, True, True]  # top,right,bottom,left
        self.mmap = mmap
        if mmap:
            mmap.mmap[x][y] = self
        self.x, self.y = x, y
        if direction is not None:
            direction = (direction + 2) % 4    #变换方向
            self.walls[direction] = False

    def __unicode__(self):
        return "%s" % [1 if e else 0 for e in self.walls]

    def __str__(self):
        return unicode(self).encode('utf-8')
    #控制方向
    def get_next_block_pos(self, direction):
        x = self.x
        y = self.y
        if direction == 0:  # 向下
            y -= 1
        elif direction == 1:  # 向右
            x += 1
        if direction == 2:  # 向上
            y += 1
        if direction == 3:  # 向左
            x -= 1
        return x, y

    def get_next_block(self):
        directions = list(range(4))#在0，1，2，3这4个数中随机生成
        random.shuffle(directions)#随机生成方向
        for direction in directions:
            x, y = self.get_next_block_pos(direction)
            if x >= self.mmap.max_x or x < 0 or y >= self.mmap.max_y or y < 0:
                continue              #如果超出了图形边界，则此次路线无效
            if self.mmap.mmap[x][y]:  # 如果这个点走过了，即绕成圈了，排除此次班block
                continue
            self.walls[direction] = False
            return Block(self.mmap, x, y, direction)
        return None


class Map(object):
    #定义重置地图
    def reset_map(self):
        self.gen_map(self.max_x, self.max_y)
        

    def gen_map(self, max_x=10, max_y=10):
        self.max_x, self.max_y = max_x, max_y
        self.mmap = [[None for j in range(self.max_y)] for i in range(self.max_x)]
        self.solution = []
        #起始地位置
        block_stack = [Block(self, 0, 0)]  # a unused block
        while block_stack:
            block = block_stack.pop()
            #如果走不到终点将里面的线路清空
            next_block = block.get_next_block()
            #如果可以找到下一个block，则一直进行，并临时性的存入block_stack中
            if next_block:
                block_stack.append(block)
                block_stack.append(next_block)
                if next_block.x == self.max_x - 1 and next_block.y == self.max_y - 1:  # is end
                    for o in block_stack:
                        #递归
                        self.solution.append((o.x, o.y))

    def __unicode__(self):                           #编码的转化
        out = ""
        for y in range(self.max_y):
            for x in range(self.max_x):
                out += "%s" % self.mmap[x][y]
            out += "\n"
        return out

    def __str__(self):
        return unicode(self).encode('utf-8')        #


class DrawMap(object):
    def __init__(self, mmap, cell_width=(1000)):
        self.mmap = mmap
        self.cell_width = cell_width

    def get_map_size(self):
        # width, height
        return (self.mmap.max_x + 2) * self.cell_width, (self.mmap.max_y + 2) * self.cell_width

    def create_line(self, x1, y1, x2, y2, **kwarg):         #排除报错，
        raise NotImplemented()

    def create_solution_line(self, x1, y1, x2, y2):
        self.create_line(x1, y1, x2, y2)

    def draw_start(self):
        raise NotImplemented()

    def draw_end(self):
        raise NotImplemented()

    def get_cell_center(self, x, y):
        w = self.cell_width
        return (x + 1) * w + w // 2, (y + 1) * w + w // 2

    def draw_solution(self):
        begin = (0, 0)
        for o in self.mmap.solution:
            p1 = self.get_cell_center(*begin)                   
            p2 = self.get_cell_center(*o)
            self.create_solution_line(p1[0], p1[1], p2[0], p2[1])
            begin = o
    def draw_track(self):
       raise    NotImplemented()       

    def draw_cell(self, block):
        width = self.cell_width
        x = block.x + 1
        y = block.y + 1
        walls = block.walls
        if walls[0]:
            self.create_line(x * width, y * width, (x + 1) * width + 1, y * width)
        if walls[1]:
            self.create_line((x + 1) * width, y * width, (x + 1) * width, (y + 1) * width + 1)
        if walls[2]:
            self.create_line(x * width, (y + 1) * width, (x + 1) * width + 1, (y + 1) * width)
        if walls[3]:
            self.create_line(x * width, y * width, x * width, (y + 1) * width + 1)
    #画出迷宫的形状
    def draw_map(self):
        for y in range(self.mmap.max_y):
            for x in range(self.mmap.max_x):
                self.draw_cell(self.mmap.mmap[x][y])     
        self.draw_start()
        self.draw_end()
        # self.draw_track()
      

class TKDrawMap(DrawMap):
    def __init__(self, mmap):
        #使父类DrawMap中的方法TKDrawMap可以全部使用
        super(TKDrawMap, self).__init__(mmap, cell_width=10)
        #创建页面
        master = Tk()
       
        #label=Label(master,image=img)
        #label.pack(side = "top")
        #定义尺寸
        width, height = self.get_map_size()
        #canvas为画布
        self.w = Canvas(master, width=width, height=width)
        self.w.pack()

        self.draw_map()
        master.mainloop()
        
    #起始点
    def draw_start(self):
        r = self.cell_width // 3
        x, y = self.get_cell_center(0, 0)
        start = self.w.create_polygon((x - r-5, y - r-5,x,y, x + r+5, y - r-5), fill="yellow")
        self.w.tag_bind(start, '<ButtonPress-1>', lambda e:self.draw_solution() or self.draw_track())
        self.w.create_text((x+17,y),text = 'Rouse',anchor = W)

    def draw_track(self,index=0):#未实现的代码，如果使用程序会无影响
        r = self.cell_width // 3
        self.w.delete("a")
        x,y = self.mmap.solution[index]
        x,y = self.get_cell_center(x,y)
        self.w.create_oval(x - r, y - r, x + r, y + r, fill="red", tags="a")
        index+=1
        if index<len(self.mmap.solution):
            self.w.after(50,self.draw_track,index)
        # self.w.master.after(200, self.draw_ball(x - r, y - r, x + r, y + r))


#终止点
    def draw_end(self):
        #圆的半径
        r = self.cell_width // 3
        x, y = self.get_cell_center(self.mmap.max_x - 1, self.mmap.max_y - 1)
        #画圆
        end = self.w.create_polygon((x + r+5, y + r+5,x,y, x - r-5, y + r+5), fill="red")
        #将圆和鼠标左键进行绑定
        self.w.tag_bind(end, '<ButtonPress-1>', lambda e: self.reset_map())
        self.w.create_text((x-53,y),text = 'Change',anchor = W)
    #进行地图的重置，更新
    def reset_map(self):
        self.mmap.reset_map()
        #删除
        self.w.delete('all')
        #重新画地图
        self.draw_map()

    #定义一个画线的函数
    def create_line(self, x1, y1, x2, y2, **kwargs):#关键字参数，是一个字典，将x，y存放的值进行提取
        self.w.create_line(x1, y1, x2, y2, **kwargs)
    #画出放于solution中的线
    def create_solution_line(self, x1, y1, x2, y2):
        self.create_line(x1, y1, x2, y2, fill="red")

def main():
    m = Map()
    #画出地图
    m.gen_map(70, 65)
    #放入一些设置并画出路线
    TKDrawMap(m)

if __name__ == '__main__':
    main()
